import Mock from 'mockjs'
import qs from 'qs'
import withCredentials from '../patch/withCredentials'

/* 补丁 */
withCredentials(Mock)

/* Mock 默认配置 */
Mock.setup({ timeout: '200-300' })

/* 扩展 [生成器] */
const Generator = (prop, template) => {
	const obj = {}
	obj[prop] = [template]
	return Mock.mock(obj)
}

/* 扩展 [循环] */
const Repeat = (num, itemTemplate) => Generator(`data|${num}`, itemTemplate).data


const CustomExtends = {
	Generator,
	Repeat,
	Mock,
	Random: Mock.Random
}

/**
 * vbyzc
 * 引用axios的时候，使用了qs来序列化，才能发送formdata
 * 下面需要用到json对象，这个方法用来json序列转为json对象
 * @param {*} jsonstring
 */
const jsonStringToJson = (jsonstring) => {
	return jsonstring.split('&').reduce((prev,cur) => {
		let p = cur.split('=')
		prev[p[0]] = p[1]
		return prev
	},{});
}

/**
 * 扩展mock对象的参数？？？
 * @param {*} param0
 */
const wired = ({ url, type, body }) => {
	return {
		method: type,
		params: qs.parse(url.split('?').length > 1 ? url.split('?')[1] : ''),
		// body: JSON.parse(body), //引用axios的时候，使用了qs来序列化，才能发送formdata,  这里如果再使用JSON.parse会出错，所以在下增加了兼容方法
		body: typeof body == 'string' ? jsonStringToJson(body) : body,
		url: qs.parse(url.split('?')[0]),
		...CustomExtends
	}
}

/**
 * 扩展安装模拟数据方法
 * @param {url,内部会使用RegExp转为正则} path
 * @param {方法} method
 * @param {数据,如果是一个函数，面积可以接收参数来模拟处理并返回相应数据} handle
 */
const setup = (path, method, handle) => {
	Mock.mock(
		RegExp(path),
		method,
		typeof handle === 'function' ? o => handle(wired(o)) : handle
	)
}

/**
 * 用于遍历处理mock数据，用来处理多个请求方法
 * @param {传入的数据对象} collection
 */
const load = (collection) => {
	collection.map(({ path, method, handle }) => {
		// 如果传入的请求方法是*，则设置成所有方法
		if (method === '*') {
			method = [
				'get',
				'GET',
				'head',
				'post',
				'POST',
				'put',
				'delete',
			]
		}
		// 如果安装的模拟数据设置多个请求方法，如  'get|post' ,则转成数组
		if (typeof method === 'string' && method.indexOf('|') > -1) {
			method = method.split('|')
		}
		// 如果转成了数组
		if (method instanceof Array) {
			// 则遍历重新设置的方法数组，以不同的方法但相同的数据，来安装本次传入的模拟数据
			method.map(item => setup(path, item, handle))
		} else {
			// 不然就按原传入方法安装数据
			setup(path, method, handle)
		}
	})
}

export default { load }
